#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <errno.h>
#include <unistd.h>
#define EMPTY 0
#define FULL 1
#define N 10
typedef void* (*fun)(void*);
/*Stauts: 
*	1: full
*	0: empty
* 
*/
int data_len =0;
typedef struct _status{
	sem_t avail;
	sem_t full[2];
	sem_t empty[2];
}status_type;

void* thread1(status_type* status);
void* thread2(status_type* status);

/*
 *  when program is started, a single thread is created, called the initial thread or main thread.
 *  Additional threads are created by pthread_create.
 *  So we just need to create two thread in main().
 */

int main(int argc, char** argv)
{
	printf("enter main\n");
	pthread_t tid1, tid2;
	int rc1=0, rc2=0;
	data_len = 5;
	status_type* status = NULL;
	status = (status_type *) malloc( sizeof(status_type));
	/*init sem*/
	sem_init(&status->avail, 0, data_len);
	sem_init(&status->full[0], 0, 0);
	sem_init(&status->full[1], 0, 0);
	sem_init(&status->empty[0], 0, 1);
	sem_init(&status->empty[1], 0, 1);

	rc2 = pthread_create(&tid2, NULL, (void*)thread2, status);
	if(rc2 != 0)
		printf("%s: %d\n",__func__, strerror(rc2));

	rc1 = pthread_create(&tid1, NULL, (void*)thread1, status);
	if(rc1 != 0)
		printf("%s: %d\n",__func__, strerror(rc1));

	pthread_join(tid1, NULL);

	/*clear sem*/
	sem_destroy(&status->avail);
	sem_destroy(&status->full[0]);
	sem_destroy(&status->full[1]);
	sem_destroy(&status->empty[0]);
	sem_destroy(&status->empty[1]);
	printf("leave main\n");
	exit(0);	
}

/*
 * thread1() will be execute by thread1, after pthread_create()
 * it will set status = 1;
 */
void* thread1(status_type* status)
{
	struct timeval now;
	struct timespec outtime; 
    gettimeofday(&now, NULL);
	int file_len = data_len;
	int i=0;
	int j=0;
	while(i < file_len ){
		sem_wait(&status->full[i & 0x1]);
		
		printf("\t\t%d: Write %d file start...\n",i, i&0x1);
		
		sleep(5);
		printf("\t\twrite file done!\n");
		sem_post(&status->empty[i & 0x1]);
		i++;	
	}
	printf("\t\tleave thread1\n");
	pthread_exit(0);
}

/*
 * thread2() will be execute by thread2, after pthread_create()
 * it will set status = 2;
 */
void* thread2(status_type* status)
{
	int i=0;
	int j=0;
	while(i < data_len ){

		sem_wait(&status->empty[i & 0x1]);
		printf("%d:Read %d memory ... start\n", i, i&0x1);

		/*for(j =0 ; j< 5; j++)*/
			/*printf("Read memory\n");*/
//		sleep(2);
			printf("Read memory done!\n");
		sem_post(&status->full[i & 0x1]);
			i++;

	}
	printf("leave thread2\n");
	pthread_exit(0);
}
